package com.bear.fastrepair.mvvm.ui.login

import android.graphics.Bitmap
import android.util.Patterns
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.bear.fastrepair.R
import com.bear.fastrepair.entity.EmployeeInfo2
import com.bear.fastrepair.mvvm.data.Result.*
import com.bear.fastrepair.mvvm.data.login.LoginRepository
import com.bear.fastrepair.mvvm.data.model.LoggedInUser
import com.bear.fastrepair.utils.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext


class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel() {

    var webSocketStart = false

    private val _loginForm = MutableLiveData<LoginFormState>()
    val loginFormState: LiveData<LoginFormState> = _loginForm

    private val _loginResult = MutableLiveData<LoginResult>()
    val loginResult: LiveData<LoginResult> = _loginResult

    private val _loginVerificationCode = MutableLiveData<Bitmap?>()
    val loginVerificationCode: LiveData<Bitmap?> = _loginVerificationCode

    private val _loginLoggedInUser = MutableLiveData<LoggedInUser?>()
    val loginLoggedInUser: LiveData<LoggedInUser?> = _loginLoggedInUser


    private val _personalInfo = MutableLiveData<EmployeeInfo2>()
    val personalInfo: LiveData<EmployeeInfo2> = _personalInfo

    fun login(
        username: String,
        password: String,
        loginType: Int,
        verificationCode: String? = null
    ) {
        // can be launched in a separate asynchronous job
        launch {
            when (val result =
                loginRepository.login(username, password, loginType, verificationCode)) {
                is Success -> _loginResult.value =
                    LoginResult(
                        success = ResponseInfoView(
                            displayName = result.data.msg,
                            loginType
                        )
                    )
                is Error -> _loginResult.value = LoginResult(error = result.data?.code)
            }
        }
    }

    fun getVerificationCode() = launch {
        _loginVerificationCode.value = loginRepository.getVerificationCode()
    }

    fun loginDataChanged(username: String, password: String) {
        if (!isUserNameValid(username)) {
            _loginForm.value = LoginFormState(usernameError = R.string.invalid_username)
        } else if (!isPasswordValid(password)) {
            if (password.length <= 5) _loginForm.value =
                LoginFormState(passwordError = R.string.invalid_password)
            else if (password.length > 20) _loginForm.value =
                LoginFormState(passwordError = R.string.invalid_password_long)
        } else {
            _loginForm.value = LoginFormState(isDataValid = true)
        }
    }

    // A placeholder username validation check
    private fun isUserNameValid(username: String): Boolean {
        return if (username.contains("@")) {
            Patterns.EMAIL_ADDRESS.matcher(username).matches()
        } else {
            username.isNotBlank() && run {
                var result = true
                arrayOf("-", "!", "#", "$", "%", "^", "&", "*", "+").forEach {
                    if (username.startsWith(it)) {
                        result = false
                        return@forEach
                    }
                }
                result
            }
        }
    }

    // A placeholder password validation check
    private fun isPasswordValid(password: String): Boolean {
        return password.length in 6..19
    }

    fun getLoggedInUser() = launch {
        withContext(Dispatchers.IO) {
            val userName = SharedPreferencesHelper.getString(ACCOUNT_KEY)
            if (userName == null || userName.isEmpty()) {
                _loginLoggedInUser.postValue(null)
                return@withContext
            }
            val password = SharedPreferencesHelper.getString(PASSWORD_KEY)
            val type = SharedPreferencesHelper.getInt(ACCOUNT_TYPE_KEY)
            _loginLoggedInUser.postValue(LoggedInUser(userName, password, type))
        }
    }

    fun getPersonalInfo() = launch {
        when (val result = loginRepository.getPersonalInfo()) {
            is Success -> _personalInfo.value = result.data
            is Error -> _personalInfo.value = result.data!!
        }
    }
}